package logic

import (
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"iot-base/auth/db"
	"iot-base/auth/model"
	"iot-base/auth/svc"
	"iot-base/auth/types"
	"iot-base/auth/utils"
	"iot-base/common/jwt"
	"sort"
	"strconv"
	"time"
)

type UserLogin struct {
}

func NewUserLogic() *UserLogin {
	return &UserLogin{}
}

func (l *UserLogin) LoginToken(username, password string) (string, model.User, error) {
	var userInfo model.User
	token := ""
	userModel := svc.Dao.TUser
	userInfo, err := userModel.GetUserByUserName(username)
	if err != nil {
		return token, userInfo, errors.New("用户不存在")
	}
	if userInfo.UserName == "" {
		return token, userInfo, errors.New("用户名或密码错误")
	}
	if userInfo.Status == 2 {
		return token, userInfo, errors.New("该用户已禁止登录")
	}
	if userInfo.ExpireTime.NullTime.Valid {
		if time.Now().Unix() > userInfo.ExpireTime.NullTime.Time.Unix() {
			return token, userInfo, errors.New("此账号已过期")
		}
	}
	//fmt.Println("用户密码:", utils.GetMd5Pwd(password, userInfo.Salt))
	if utils.GetMd5Pwd(password, userInfo.Salt) != userInfo.PassWord {
		return token, userInfo, errors.New("用户名或密码错误")
	}
	jwtObj := jwt.NewJWT()
	custom := jwt.CustomClaims{}
	custom.ID = strconv.FormatInt(userInfo.ID, 10)
	custom.ExpiresAt = time.Now().Add(time.Hour * 2).Unix()
	token, _ = jwtObj.CreateToken(custom)
	db.NewRedis().HSet(db.KeyUserLogin, custom.ID, token)
	return token, userInfo, nil
}

func (l *UserLogin) AddUser(userId int64, user types.ReqAddUser) error {
	userMode := svc.Dao.TUser
	num, err := userMode.FindCount(user.UserName)
	if err != nil {
		return err
	}
	if num >= 1 {
		return errors.New("用户名已存在。")
	}
	userInfo, err := userMode.GetById(userId)
	if err != nil {
		return err
	}
	var userData model.User
	userData.ID = utils.GetUid()
	userData.UserType = user.UserType
	userData.UserName = user.UserName
	userData.NickName = user.UserName
	userData.Phone = user.Phone
	userData.Email = user.Email
	userData.Salt = utils.GetRandomString(6)
	userData.CreatedAt = time.Now()
	userData.UpdatedAt = userData.CreatedAt
	userData.PassWord = utils.GetMd5Pwd(user.PassWord, userData.Salt)
	userData.CompanyId = userInfo.CompanyId
	userData.Facsimile = user.Facsimile
	userData.FixedPhone = user.FixedPhone
	if user.ExpireTime != "" {
		exp, err := utils.StringToTime(user.ExpireTime)
		if err != nil {
			return err
		}
		userData.ExpireTime.NullTime.Time = exp
		userData.ExpireTime.NullTime.Valid = true
	}

	err = userMode.AddUser(&userData)
	if err != nil {
		fmt.Println("orm", err)
		return err
	}
	if len(user.UserGroups) > 0 {
		userGroupLogic := NewUserGroupLogic()
		return userGroupLogic.EditUserGroup(userData.ID, user.UserGroups)
	}
	return nil
}

func (l *UserLogin) UpdateUser(user types.ReqUpdateUser) error {
	userMode := svc.Dao.TUser
	var userData model.User
	userData.NickName = user.NickName
	userData.Phone = user.Phone
	userData.Email = user.Email
	userData.Status = user.Status
	userData.UserType = user.UserType
	userData.UpdatedAt = time.Now()
	userData.Facsimile = user.Facsimile
	userData.FixedPhone = user.FixedPhone
	if user.ExpireTime != "" {
		exp, err := utils.StringToTime(user.ExpireTime)
		if err != nil {
			return err
		}
		userData.ExpireTime.NullTime.Time = exp
		userData.ExpireTime.NullTime.Valid = true
	} else {
		userData.ExpireTime.NullTime.Valid = false
	}
	err := userMode.Update(user.ID, userData)
	if err != nil {
		return err
	}
	if len(user.UserGroups) > 0 {
		userGroupLogic := NewUserGroupLogic()
		return userGroupLogic.EditUserGroup(user.ID, user.UserGroups)
	}
	return nil
}

func (l *UserLogin) Del(id int64) error {
	userMode := svc.Dao.TUser
	return userMode.Del(id)
}
func (l *UserLogin) FindCount(userName string) (int64, error) {
	userMode := svc.Dao.TUser
	return userMode.FindCount(userName)
}

func (l *UserLogin) FindList(userName string, page, size int) ([]model.User, error) {
	userMode := svc.Dao.TUser
	return userMode.Find(userName, page, size)
}

func (l *UserLogin) UserList(uid int64, req types.ReqFindUser) (gin.H, error) {
	resp := gin.H{
		"total": 0,
		"list":  make([]interface{}, 0),
	}
	// 查询用户组
	// 取出当前管理的分组.
	groupModel := svc.Dao.TAuthGroup
	groups, err := groupModel.GetUserGroup(uid)
	if err != nil {
		return resp, err
	}
	groupIds := make([]int64, 0, len(groups))
	if req.GroupId == 0 {
		for k := range groups {
			groupIds = append(groupIds, groups[k].ID)
			path := groups[k].Path
			if groups[k].Pid == 0 {
				path = strconv.FormatInt(groups[k].ID, 10)
			}
			groupNode, err := groupModel.FindChildNode(path)
			if err != nil {
				continue
			}
			for index := range groupNode {
				groupIds = append(groupIds, groupNode[index].ID)
			}
		}
	} else {
		groupIds = append(groupIds, req.GroupId)
	}
	userMode := svc.Dao.TUser
	total, err := userMode.FindGroupUserCount(groupIds, req.UserName)
	if err != nil {
		return resp, err
	}
	result, err := userMode.FindGroupUser(groupIds, req.UserName, req.Page, req.Size)
	if err != nil {
		return resp, err
	}
	resp["total"] = total
	resp["list"] = result
	return resp, nil
}

// DetailUser 查询用户详情.
func (l *UserLogin) DetailUser(userId int64) (gin.H, error) {
	resp := gin.H{}
	userModel := svc.Dao.TUser
	userInfo, err := userModel.GetById(userId)
	if err != nil {
		return resp, err
	}
	companyModel := svc.Dao.TCompany
	company, err := companyModel.Get(userInfo.CompanyId)
	if err != nil {
		return resp, err
	}
	userGroup, err := svc.Dao.TUserGroup.FindUserRoleByUid(userInfo.ID)
	if err != nil {
		return resp, err
	}
	auths := make([]map[string]interface{}, 0, len(userGroup))
	for _, value := range userGroup {
		auths = append(auths, gin.H{
			"group_id":   value.Group.ID,
			"group_name": value.Group.GroupName,
			"role_id":    value.Role.ID,
			"role_name":  value.Role.RoleName,
		})
	}
	resp["user"] = userInfo
	resp["company"] = company
	resp["auths"] = auths
	return resp, nil
}

// ResetPwd 重置密码
func (l *UserLogin) ResetPwd(userId int64, pwd string) error {
	userMode := svc.Dao.TUser
	var userData model.User
	userData.Salt = utils.GetRandomString(6)
	userData.CreatedAt = time.Now()
	userData.PassWord = utils.GetMd5Pwd(pwd, userData.Salt)
	userData.UpdatedAt = time.Now()
	return userMode.Update(userId, userData)
}

// ChangePwd 修改密码.
func (l *UserLogin) ChangePwd(userId int64, pwd string, newPwd string) (int, error) {
	user, err := svc.Dao.TUser.GetById(userId)
	if err != nil {
		return types.DBError, err
	}
	if utils.GetMd5Pwd(pwd, user.Salt) != user.PassWord {
		return types.UserOrPwdERR, nil
	}
	err = l.ResetPwd(userId, newPwd)
	if err != nil {
		return types.DBError, err
	}
	return types.Success, nil
}

// IsSysAdmin 判断用户是否是系统管理员.
func (l *UserLogin) IsSysAdmin(userId int64) (bool, error) {
	uidStr := strconv.FormatInt(userId, 10)
	redis := db.NewRedis()
	uid, _ := redis.Get("IsSysAdmin")
	if uid == "" {
		userGroup, err := svc.Dao.TUserGroup.FindUserRoleByUid(userId)
		if err != nil {
			return false, err
		}
		if len(userGroup) <= 0 {
			return false, nil
		}
		sort.Slice(userGroup, func(i, j int) bool {
			return userGroup[i].ID < userGroup[j].ID
		})
		if userGroup[0].ID == 1 {
			redis.Set("IsSysAdmin", uidStr, time.Hour*24)
			return true, nil
		}
	} else {
		if uid == uidStr {
			return true, nil
		}
	}

	return false, nil
}

func (l *UserLogin) CheckThingAuth(userId int64, stationId string) bool {
	// 判断用户是否是系统管理员.
	isSysAdmin, _ := l.IsSysAdmin(userId)
	if isSysAdmin == true {
		return true
	}
	list, err := NewStationLogic().GetStationIds(userId)
	if err != nil {
		return false
	}
	for _, v := range list {
		if v == stationId {
			return true
		}
	}
	return false
}

// CheckThingIdIsAuth 通过设备ID监测是是否有权限.
func (l *UserLogin) CheckThingIdIsAuth(userId int64, thingId string) bool {
	// 判断用户是否是系统管理员.
	isSysAdmin, _ := l.IsSysAdmin(userId)
	if isSysAdmin == true {
		return true
	}
	// 获取设备ID
	thingInfo, err := svc.Dao.TThingStation.FindStationId(thingId)
	if err != nil {
		return false
	}
	return l.CheckThingAuth(userId, thingInfo.ThingID)
}
